
using System;

namespace MxitAPI {
	
	/**
	 * Abstract base class for all Handlers. 
	 * Commands are used to populate messages.
	 * They are created by the event handler, they create a message and then send it to the Mxit server
	 * They then act on the response returned by the Mxit server
	 */
	public abstract class Handler {	
			
		private static log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
		
		private Type protocolMessageType;
		
		protected Handler() {
			init();
		}
		
		protected Handler( Type protocolMessageType ) {
			this.protocolMessageType = protocolMessageType;
			log.DebugFormat( "Handler Created. Type [{0}]", this.GetType() );
		}
		
		public virtual void init() {
		}
		
		/**
		 * Begins the excecution of the entire process of handling a message event
		 * from creating the message and sending it to the Mxit server, to hanldling the response
		 */
		public virtual void Execute() {
			// Creates an instance of the delegate so that CreateRequestMessage can be called once the message response is ready
			
			log.DebugFormat( "Handler being executed. Type [{0}]", this.GetType() );
			
			ProtocolMessage message = CreateRequestProtocolMessage();
			
			if ( message.MessageResponseHandler == null ) {
				//MessageResponseHandler messageResponseHandler = new MessageResponseHandler( HandleResponseProtocolMessage );
				//message.MessageResponseHandler = messageResponseHandler;
			}
            ProtocolMessageSendQueue sendQueue = ProtocolMessageSendQueue.Instance;
            sendQueue.AddProtocolMessage( message );
		}
		
		public virtual ProtocolMessage CreateRequestProtocolMessage() {
			ProtocolMessage protocolMessage = ( ProtocolMessage ) Activator.CreateInstance( protocolMessageType );
			return protocolMessage;
		}
		
		protected virtual void HandleResponseProtocolMessageHeader( ProtocolMessage protocolMessage  ) {
            if ( protocolMessage.ErrorCode != ErrorCode.NoError ) {
                ApplicationInfo.Instance.DoProtocolMessageError( this, protocolMessage );
                //throw new MxitProtocolMessageException( "Error returned by mxit for messageHandler type: " + this.GetType(), protocolMessage.ErrorCode, protocolMessage.ErrorMessage );

            }
			
		}
		
		protected virtual void HandleSpecificResponseProtocolMessage( ProtocolMessage protocolMessage ) {
		}
		
		public virtual void HandleResponseProtocolMessage( ProtocolMessage protocolMessage ) {
			log.DebugFormat( "Handling header of response protocol message. ProtocolMessage type [{0}]", protocolMessage.GetType() );
			HandleResponseProtocolMessageHeader( protocolMessage );
			HandleSpecificResponseProtocolMessage( protocolMessage );
		}
		
		public static Handler GetHandler( ProtocolMessage protocolMessage ) {
			Handler handler;
			// Todo remove null after all protocol messages have been implimented
			handler = null;
			
			switch ( protocolMessage.ProtocolMessageType ) {
			case ProtocolMessageType.Login:
				handler = new LoginHandler();
				break;
			case ProtocolMessageType.Logout:
				handler = new LogoutHandler();
				break;
			case ProtocolMessageType.GetContacts:
				handler = new GetContactsHandler();
				break;
			case ProtocolMessageType.UpdateContactInfo:
				handler = new UpdateContactInfoHandler();
				break;
			case ProtocolMessageType.SubscribeToContact:
				handler = new SubscribeToContactHandler();
				break;
			case ProtocolMessageType.RemoveContact:
				handler = new RemoveContactHandler();
				break;
			case ProtocolMessageType.GetNewMessages:
				handler = new GetNewMessagesHandler();
				break;
			case ProtocolMessageType.SendMessage:
				handler = new SendMessageHandler();
				break;
			case ProtocolMessageType.Register:
				//handler = new LoginHandler();
				break;
			case ProtocolMessageType.UpdateProfile:
				handler = new UpdateProfileHandler();
				break;
			case ProtocolMessageType.PollDifference:
				//handler = new LoginHandler();
				break;
			case ProtocolMessageType.GetProfile:
				handler = new GetProfileHandler();
				break;
			case ProtocolMessageType.GetMultimediaMessage:
				handler = new GetMultimediaMessageHandler();
				break;
			case ProtocolMessageType.RenameGroup:
				//handler = new LoginHandler();
				break;
			case ProtocolMessageType.RemoveGroup:
				//handler = new LoginHandler();
				break;
			case ProtocolMessageType.SplashScreenClickThrough:
				//handler = new LoginHandler();
				break;
			case ProtocolMessageType.SetPresence:
				handler = new SetPresenceHandler();
				break;
			case ProtocolMessageType.BlockSubscription:
				handler = new BlockSubscriptionHandler();
				break;
			case ProtocolMessageType.SendMessageToGroup:
				//handler = new LoginHandler();
				break;
			case ProtocolMessageType.SetMood:
				handler = new SetMoodHandler();
				break;
			case ProtocolMessageType.LoginKick:
				//handler = new SetMoodHandler();
				break;
			case ProtocolMessageType.CreateGroupChat:
				handler = new CreateGroupChatHandler();
				break;
			case ProtocolMessageType.AddGroupChatMember:
				handler = new AddGroupChatMembersHandler();
				break;	
			case ProtocolMessageType.GetNewSubscription:
				handler = new GetNewSubscriptionHandler();
				break;
			case ProtocolMessageType.AllowSubscription:
				handler = new AllowSubscriptionHandler();
				break;
			case ProtocolMessageType.RegisterGateway:
				handler = new RegisterGatewayHandler();
				break;
			case ProtocolMessageType.DenySubscription:
				handler = new DenySubscriptionHandler();
				break;
			case ProtocolMessageType.UnregisterGateway:
				handler = new UnregisterGatewayHandler();
				break;
			case ProtocolMessageType.KeepAlive:
				handler = new KeepAliveHandler();
				break;
			default:
				handler = null;
				break;
			}
			
			//handler.CreateRequestProtocolMessage( protocolMessage );
			if ( handler == null )
				throw new MxitException( "A handler could not be found for this ProtocolMessage type." );
			
			log.DebugFormat( "A new handler was created using a MessageType with type [{0}]", handler.GetType() );
			
			return handler;
		}
		
		
	}
}
